package com.example.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.util.ByteArrayBuffer;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;

public class FileUtil {
	public static final String ANDROID_FILE_PREFIX = "file://";
	public static final int TIMEOUT_CONNECTION = 5000;
	public static final int TIMEOUT_READ = 3000;

	public static String concatePath(String path1, String path2) {
		if (StringUtil.isEmpty(path1)) return path2;
		if (StringUtil.isEmpty(path2)) return path1;
		
		path1 = path1.replace("\\\\", "/");
		path2 = path2.replace("\\\\", "/");

		return (path1 + "/" +path2).replaceAll("[/]+", "/");
	}
	
	public static List<String> getFileList(final String path) throws IOException {
		List<String> fileList = new ArrayList<String>();
		File file = new File(path);
		if (!file.exists())
			return null;
		
		traverse(fileList, file);
		
		return fileList;
	}
	
	public static List<String> getFileList(final String path, boolean isRecursive) throws IOException {
		List<String> fileList = new ArrayList<String>();
		File file = new File(path);
		if (!file.exists())
			return null;
		
		if (isRecursive)
			traverse(fileList, file);
		else {
			if (!file.isDirectory())
				return fileList;

			File[] files = file.listFiles();
			if (files == null || files.length < 1)
				return fileList;

			for (File child : files) {
				if (child.isFile())
					fileList.add(child.getPath());
			}
		}
		
		return fileList;
	}
	
	public static void traverse(List<String> list, final File f) throws IOException {
		if (f.isDirectory()) {
			final File[] childs = f.listFiles();
			for (File child : childs)
				traverse(list, child);
		}
		else
			list.add(f.getPath());
	}
	
	public static void traverse(List<String> list, final File f, final String prefix) throws IOException {
		if (f.isDirectory()) {
			final File[] childs = f.listFiles();
			for (File child : childs)
				traverse(list, child, prefix);
		}
		else
			list.add(prefix + f.getPath());
	}
	
	public static boolean makeDir(String filename) {
		boolean isSuccess = false;
		String path = getPath(filename);
		File file = new File(path);
		if(!file.exists()) {
			isSuccess = file.mkdirs();
		}
		return isSuccess;
	}
	
	public static boolean write(String filename, String contents) {
		File file = new File(filename);
		BufferedWriter out = null;
		try {
			makeDir(getPath(filename));
			out = new BufferedWriter(new FileWriter(file));
			out.write(StringUtil.nvl(contents));
		} 
		catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		finally {
			if (out != null) try { out.close(); } catch (IOException e) {}
		}
		
		return file.exists();
	}
	
	public static boolean write(String filename, byte[] contents) {
		File file = new File(filename);
		FileOutputStream out = null;
		try {
			makeDir(getPath(filename));
			out = new FileOutputStream(file);
			out.write(contents);
		}
		catch (IOException e) {
			e.printStackTrace();
			return false;
		} 
		finally {
			if (out != null) try { out.close(); } catch (IOException e) {}
		}
		
		return file.exists();
	}
	
	public static String getFileExtend(String filename) {
		String[] tmpArray = StringUtil.split(filename, ".");

		if (tmpArray == null || tmpArray.length < 1)
			return filename;
		else
			return tmpArray[tmpArray.length - 1];
	}

	public static String getFileName(String filename) {
		if (filename == null || filename.equals(""))
			return "";
		
		int index = filename.lastIndexOf('/');
		if (index != -1)
			return  filename.substring(index + 1);
		else
			return filename;
	}
	
	public static String getTimestampFromFileName(String fileName) {
		fileName = FileUtil.getFileName(fileName);
		
		if (fileName == null || "".equals(fileName) || fileName.length() < 15)
			return fileName;
		
		StringBuffer date = new StringBuffer(); 
		date.append(fileName.substring(0, 4)).append("년")
			.append(fileName.substring(4, 6)).append("월")
			.append(fileName.substring(6, 8)).append("일 ")
			.append(fileName.substring(9, 11)).append(":")
			.append(fileName.substring(11, 13)).append(":")
			.append(fileName.substring(13, 15));
		
		return date.toString();
	}
	
	public static String getPath(String filename) {
		if (filename == null || filename.equals(""))
			return "";
		
		int index = filename.lastIndexOf('/');
		if (index != -1)
			return  filename.substring(0, index);
		else
			return filename;
	}
	
	public final static boolean copy(File fromFile, File toFile) {
		FileInputStream in = null;
		FileOutputStream out = null;
		BufferedInputStream inBuffer = null;
		BufferedOutputStream outBuffer = null;
		
		try{
			in = new FileInputStream(fromFile);
			out = new FileOutputStream(toFile);
			inBuffer = new BufferedInputStream(in);
			outBuffer = new BufferedOutputStream(out);

			int theByte = 0;
			while ((theByte = inBuffer.read()) > -1){
				outBuffer.write(theByte);
			}
			outBuffer.close();
			inBuffer.close();
			out.close();
			in.close();


			if (fromFile.length() != toFile.length()){
				toFile.delete();
				return false;
			}
			return true;
		}
		catch (IOException e){
			e.printStackTrace();
			return false;
		}
		finally {
			if (outBuffer != null) try { outBuffer.close(); } catch (IOException e) {}
			if (inBuffer != null) try { inBuffer.close(); } catch (IOException e) {}
			if (out != null) try { out.close(); } catch (IOException e) {}
			if (in != null) try { in.close(); } catch (IOException e) {}
		}
	}
	
	public static List<String> readToList(String filename) {
		BufferedReader br = null;
		
		try {
			List<String> lines = new ArrayList<String>();
			br = new BufferedReader(new FileReader(filename));
			String line = null;
			while ((line = br.readLine()) != null) {
				lines.add(line);
			}
			
			return lines;
		}
		catch (Exception e) {
			e.printStackTrace();
			return null;
			
		} 
		finally {
			if (br != null) try { br.close(); } catch (IOException e) {}
		}
	}
	
	public static String read(String filename) {
		BufferedReader br = null;
		
		try {
			StringBuffer sb = new StringBuffer();
			br = new BufferedReader(new FileReader(filename));
			String line = null;
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			return sb.toString();
		}
		catch (Exception e) {
			e.printStackTrace();
			return null;
			
		} 
		finally {
			if (br != null) try { br.close(); } catch (IOException e) {}
		}
	}

	public final static boolean move (File fromFile, File toFile){
		if(fromFile.renameTo(toFile)){
			return true;
		}

		if (copy(fromFile, toFile)){
			return fromFile.delete();
		}
		return false;
	}
	
	public static void downloadFromUrl(String imageURL, String filePath) {
		downloadFromUrl(imageURL, filePath, true, false);
	}
	
	public static void downloadFromUrl(String imageURL, String filePath, boolean enableCache, boolean overwrite) {
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		URLConnection conn = null;
    	try {
    		URL url = new URL(imageURL);
    		File file = new File(filePath);

    		if (file.exists() && !overwrite) {
    			System.err.println("파일 있음 : " + filePath);
    			return;
    		}
    		
    		makeDir(getPath(filePath));
    		
    		Log.d("FileUtil downloadFromUrl", url + " -> " + filePath);

    		
    		conn = url.openConnection();
    		conn.setConnectTimeout(TIMEOUT_CONNECTION);
			conn.setReadTimeout(TIMEOUT_READ);
    		conn.setUseCaches(enableCache);
    		if (!enableCache) {
    			conn.setRequestProperty("Pragma", "no-cache");
    			conn.setRequestProperty("Cache-Control", "no-cache");
    			conn.setRequestProperty("Expires", "-1"); 
    		}
    		
    		bis = new BufferedInputStream(conn.getInputStream());
    		ByteArrayBuffer baf = new ByteArrayBuffer(50);
    		int current = 0;
    		byte[] buf = new byte[1024];
    		while ((current = bis.read(buf)) > 0) {
    			baf.append(buf, 0, current);
    		}

    		fos = new FileOutputStream(file);
    		fos.write(baf.toByteArray());
    		fos.close();
    	}
    	catch (IOException e) {
    		Log.d("ImageManager", "Error: " + e);
    	}
    	finally {
    		if (bis != null) try { bis.close(); bis = null; } catch (Exception ex1) {}
    		if (fos != null) try { fos.close(); fos = null; } catch (Exception ex2) {}
    	}
    }
	
	public static void delete(String filename) {
		if (filename == null || filename.trim().length() < 1)
			return;
		
		File file = new File(filename);
	    if (file.exists()) file.delete ();
	}
	
	public static void deleteFiles(String path) {
		deleteFiles(new File(path), false);
	}
	
	public static void deleteFiles(File path) {
		deleteFiles(path, false);
	}
	
	public static void deleteFiles(File path, boolean isRecursive) {
		File[] childFile = path.listFiles();
		
		if (childFile == null)
			return;
		
		for (File aFile : childFile) {
			if (aFile.isFile())
				aFile.delete();
            else
            	deleteFiles(aFile, isRecursive);
		}
	}
	
	public static boolean deleteDirs(File path) {
		if (!path.exists()) return false;
		
		File[] childFile = path.listFiles();
		
		if (childFile == null)
			return false;
		
		for (File aFile : childFile) {
			if (aFile.isDirectory())
				deleteDirs(aFile);
            else
            	aFile.delete();
		}
		
		return path.delete();
	}
	
	public static void writeObjectToFile(Context context, Object object, String filename) {

        ObjectOutputStream objectOut = null;
        try {

            FileOutputStream fileOut = context.openFileOutput(filename, Activity.MODE_PRIVATE);
            objectOut = new ObjectOutputStream(fileOut);
            objectOut.writeObject(object);
            fileOut.getFD().sync();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOut != null) {
                try {
                    objectOut.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }
    }
	
	public static boolean deleteFile(Context context, String filename) {
		return context.deleteFile(filename);
	}


    /**
     * 
     * @param context
     * @param filename
     * @return
     */
    public static Object readObjectFromFile(Context context, String filename) {

        ObjectInputStream objectIn = null;
        Object object = null;
        try {

            FileInputStream fileIn = context.getApplicationContext().openFileInput(filename);
            objectIn = new ObjectInputStream(fileIn);
            object = objectIn.readObject();

        } catch (FileNotFoundException e) {
            // Do nothing
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (objectIn != null) {
                try {
                    objectIn.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }

        return object;
    }

	public static boolean exists(String path) {
		File file = new File(path);
		return file.exists();
	}

	public static boolean saveBitmap(Bitmap bitmap, String fileName) {
		FileOutputStream fos = null;
		boolean result = false;
		
	    try {
	    	FileUtil.makeDir(fileName);
		    FileUtil.delete(fileName);
	    	fos = new FileOutputStream(fileName);
	    	
	    	Log.e("saveBitmap", "bitmap.isRecycled()=" + bitmap.isRecycled() + " bitmap.getWidth()=" + bitmap.getWidth() + " bitmap.getHeight()=" + bitmap.getHeight());
	    	if (bitmap.isRecycled())
	    		return false;
	    		
	    	bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
	    	result = FileUtil.exists(fileName);
	    } catch (Exception e) {
	    	e.printStackTrace();
	    }
	    finally {
			try { fos.flush(); fos.close(); } catch (IOException e) {}
		}
	    
	    return result;
	}
	
	public static byte[] getBytesFromFile(File file) {
		ByteArrayOutputStream ous = null;
		InputStream ios = null;
		
	    try {
	        byte []buffer = new byte[4096];
	        ous = new ByteArrayOutputStream();
	        ios = new FileInputStream(file);
	        int read = 0;
	        while ( (read = ios.read(buffer)) != -1 )
	            ous.write(buffer, 0, read);
	    }
	    catch	(IOException e) {
	    	e.printStackTrace();
	    	return null;
	    }
	    finally { 
	        try { if ( ous != null ) ous.close(); } catch ( IOException e) {}
	        try { if ( ios != null ) ios.close(); } catch ( IOException e) {}
	    }
	    
	    return ous.toByteArray();
    }
	
	public static String getThumbnailFileName(String fileName, int thumbnailSize) {
		int index = fileName.lastIndexOf('.');
		return fileName.substring(0, index) + "_"+ thumbnailSize + "x" + thumbnailSize + fileName.substring(index);
	}
	
	public static String getThumbnailFileName(String fileName) {
		int index = fileName.lastIndexOf('/');
		return fileName.substring(0, index) + "/Thumb" + fileName.substring(index);
	}
	
	public static File getAlbumStorageDir(String albumName) {
		// Get the directory for the user's public pictures directory.
		File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName);
		if (!file.mkdirs()) {
			Log.e("CardImage", "Directory not created");
		}
		return file;
	}
}